package com.softserveinc.moviedbapp.fragment;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
import android.support.v4.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.Menu;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.softserveinc.moviedbapp.R;
import com.softserveinc.moviedbapp.application.MovieDBApplication;
import com.softserveinc.moviedbapp.manager.DataManager;
import com.softserveinc.moviedbapp.model.Movie;
import com.softserveinc.moviedbapp.model.MovieInfo;
import com.softserveinc.moviedbapp.util.MovieAppConstants;

import java.text.DecimalFormat;
import java.util.List;

public class MovieDetailsFragment extends Fragment implements OnClickListener {

	private Movie movie;
	private MovieInfo movieDetails;
	private ActionBar mActionBar;
	private View mProgressBar;
	private MovieDBApplication mApplication;
	private DataManager mDataMananager;

	private boolean mNeedUpdateCastOverview = true;
	private boolean mDontNeedToGetBitmaps = true;
	private int mCurrentBackdropPosition;
	private int mCurrentOrientation;

	private final static int sScreenshotsInRowPortrait = 3;
	private final static int sScreenshotsInRowLandscape = 4;

	private static String TAG = MovieDetailsFragment.class.getSimpleName();

	public MovieDetailsFragment() {
	}

	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		Log.d(TAG, "onCreate()");

		/* indicates that this fragment has it's own menu */
		setHasOptionsMenu(true);

		movie = (Movie) getArguments().getParcelable(MovieAppConstants.MOVIE_OBJECT);

		mApplication = (MovieDBApplication) getActivity().getApplication();

		mCurrentOrientation = getResources().getConfiguration().orientation;

		/* get data from the network in a background thread */
		mDataMananager = mApplication.getDataManager();

	}

	@Override
	public void onActivityCreated(final Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		Log.d(TAG, "onActivityCreated()");

		/* get the reference to the action bar from the main fragment */
		mActionBar = ((FragmentActivity) getActivity()).getSupportActionBar();
		mProgressBar = mActionBar.getCustomView().findViewById(R.id.progressBar);

		mDataMananager.setMovieInfoFragment(new IMovieDetailsCallback() {

			@Override
			public void onGettingMovieInfo() {
				mProgressBar.setVisibility(View.VISIBLE);
			}

			@Override
			public void onMovieInfoRetrieved(final MovieInfo details) {
				Log.d(TAG, "MovieInfo FRAGMENT CALLBACK");

				movieDetails = details;
				Log.d(TAG, "onMovieInfoRetrieved(final MovieInfo movieInfo) got movie info");
				Log.d(TAG, movieDetails.toString());

				/* update trailer, overview, cast and screens */
				if (mNeedUpdateCastOverview) {
					updateTrailerButton();
					updateOverviewAndCast();
					mNeedUpdateCastOverview = false;
				}

				// logHeap();

				int backdropBitmapSize = movieDetails.getBackdropBitmaps().size();
				Log.d(TAG, "backdropBitmapSize = " + backdropBitmapSize);

				if (movieDetails.getBackdropImagesUrlsList().size() != backdropBitmapSize) {
					Log.d(TAG, "mMovieInfo.getBackdropImagesUrlsList().size() != backdropBitmapSize");

					while (backdropBitmapSize != 0 && mCurrentBackdropPosition < backdropBitmapSize) {
						updateScreenShot(movieDetails.getBackdropBitmaps().get(mCurrentBackdropPosition),
								mCurrentBackdropPosition, false);
						mCurrentBackdropPosition++;
					}
					mDataMananager.provideNextScreenForMovieInfo(movieDetails);
				} else {
					Log.d(TAG, "mMovieInfo.getBackdropImagesUrlsList().size() == backdropBitmapSize");

					if (mDontNeedToGetBitmaps == true) {
						Log.d(TAG, "mNeedToGetBitmaps == false");
						List<Bitmap> bitmaps = movieDetails.getBackdropBitmaps();
						int position = 0;
						for (Bitmap bitmap : bitmaps) {
							if (position != bitmaps.size() - 1) {
								updateScreenShot(bitmap, position, false);
							} else {
								updateScreenShot(bitmap, position, true);
							}
							position++;
						}
						/* hide progress bar when all bitmaps are loaded */
						mProgressBar.setVisibility(View.INVISIBLE);

					} else {
						Log.d(TAG, "mNeedToGetBitmaps != false");

						while (mCurrentBackdropPosition < backdropBitmapSize) {
							if (mCurrentBackdropPosition != backdropBitmapSize - 1) {
								updateScreenShot(movieDetails.getBackdropBitmaps().get(mCurrentBackdropPosition),
										mCurrentBackdropPosition, false);
							} else {
								updateScreenShot(movieDetails.getBackdropBitmaps().get(mCurrentBackdropPosition),
										mCurrentBackdropPosition, true);
							}
							mCurrentBackdropPosition++;
						}

						/* hide progress bar when all bitmaps are loaded */
						mProgressBar.setVisibility(View.INVISIBLE);
					}
				}
			}

			@Override
			public void onMovieInfoRetrievalFailed() {
				AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
				/* if getting movie list failed re-try or exit */
				builder.setMessage(R.string.want_retry).setCancelable(false)
						.setPositiveButton(R.string.retry, new DialogInterface.OnClickListener() {
							@Override
							public void onClick(final DialogInterface dialog, final int id) {
								mDataMananager.provideMovieDetails(movie.getMovieId());
							}
						}).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
							@Override
							public void onClick(final DialogInterface dialog, final int id) {
								getActivity().finish();
							}
						}).show();
			}
		});

		/* get the movieInfo from cache or download them if needed */
		Log.i(TAG, "gonna call data provider's manageMovieInfo(mMovie.getMovieId() = " + movie.getMovieId() + ")");
		mDataMananager.provideMovieDetails(movie.getMovieId());

	}

	@Override
	public void onCreateOptionsMenu(final Menu menu, final android.view.MenuInflater inflater) {
		menu.clear();
		inflater.inflate(R.menu.action_bar_movie_info, menu);
		super.onCreateOptionsMenu(menu, inflater);
	}

	@Override
	public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
		Log.d(TAG, "onCreateView()");

		View movieInfoView = inflater.inflate(R.layout.details, null);

		/* set the movie title */
		TextView movieName = (TextView) movieInfoView.findViewById(R.id.details_title);
		String name = movie.getName();
		if (movieName.length() > 40) {
			movieName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
		} else {
			movieName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
		}
		movieName.setText(name);

		/* set the release date */
		TextView movieReleaseDate = (TextView) movieInfoView.findViewById(R.id.details_release);
		String releaseDate = movie.getReleased();
		if (!releaseDate.equals("1970-01-01")) {
			movieReleaseDate.setText(releaseDate);
		} else {
			movieReleaseDate.setText("N/A");
		}

		/* set the movie poster */
		ImageView poster = (ImageView) movieInfoView.findViewById(R.id.details_poster);

		poster.setImageBitmap(movie.getPosterBitmap());

		return movieInfoView;
	}

	@Override
	public void onPause() {
		mDataMananager.cancelMovieDetailsFetching();
		mDataMananager.cancelScreensDownloading();
		mProgressBar.setVisibility(View.INVISIBLE);
		Log.d(TAG, "onPause() called gonna cancel");
		super.onPause();
	}

	public static void logHeap() {
		Double allocated = new Double(Debug.getNativeHeapAllocatedSize()) / new Double((1048576));
		Double available = new Double(Debug.getNativeHeapSize()) / 1048576.0;
		Double free = new Double(Debug.getNativeHeapFreeSize()) / 1048576.0;
		DecimalFormat df = new DecimalFormat();
		df.setMaximumFractionDigits(2);
		df.setMinimumFractionDigits(2);

		Log.d("gettings", "debug. =================================");
		Log.d("gettings", "debug.heap native: allocated " + df.format(allocated) + "MB of " + df.format(available)
				+ "MB (" + df.format(free) + "MB free)");
		Log.d("gettings",
				"debug.memory: allocated: " + df.format(new Double(Runtime.getRuntime().totalMemory() / 1048576))
						+ "MB of " + df.format(new Double(Runtime.getRuntime().maxMemory() / 1048576)) + "MB ("
						+ df.format(new Double(Runtime.getRuntime().freeMemory() / 1048576)) + "MB free)");
		Log.d("gettings", "debug. =================================");
	}

	/* show the trailer button if the trailer is available */
	private void updateTrailerButton() {
		View trailerLayout = getView().findViewById(R.id.details_play_trailer);
		if (movieDetails.getTrailerUrl() != null) {
			trailerLayout.setVisibility(View.VISIBLE);
			trailerLayout.setOnClickListener(this);
		}
	}

	private void updateOverviewAndCast() {
		/* get the view that already has been inflated */
		View movieInfoView = getView();

		/* set the movie cast */
		TextView cast = (TextView) movieInfoView.findViewById(R.id.details_cast);
		if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) {

			String[] longCast = movieDetails.getCastAsString().split(", ");

			StringBuilder stringBuilder = new StringBuilder();
			int maxCastLength = 7;
			if (longCast.length > 0) {
				stringBuilder.append(longCast[0]);
				for (int i = 1; i < maxCastLength && i < longCast.length; i++) {
					stringBuilder.append(", ");
					stringBuilder.append(longCast[i]);
				}
				cast.setText(stringBuilder.toString());
			}

		} else {
			cast.setText(movieDetails.getCastAsString());
		}

		/* set the movie overview */
		TextView overview = (TextView) movieInfoView.findViewById(R.id.details_overview);
		overview.setText(movieDetails.getOverview());
	}

	private void updateScreenShot(final Bitmap currentBackdropBitmap, final int currentBackdropPosition,
			final boolean finalBitmap) {
		mDontNeedToGetBitmaps = false;
		/* get the view that already has been inflated */
		View view = getView();
		if (view == null) {
			Log.d(TAG, "updateScreenShot() called but view is null");
			return;
		}
		LinearLayout linearLayoutBottom = (LinearLayout) view.findViewById(R.id.linearLayoutBottom);

		if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) {
			Log.d(TAG, "ORIENTATION_PORTRAIT");

			LinearLayout screenshotRow;
			if (currentBackdropPosition % sScreenshotsInRowPortrait == 0) {
				Log.d(TAG, "creating screenshotRow with id "
						+ (1231 + currentBackdropPosition / sScreenshotsInRowPortrait));
				screenshotRow = (LinearLayout) View.inflate(getActivity(), R.layout.screen_shots_row, null);
				screenshotRow.setId(1231 + currentBackdropPosition / sScreenshotsInRowPortrait);
				setBitmapToImageView(currentBackdropBitmap, screenshotRow, currentBackdropPosition,
						sScreenshotsInRowPortrait, finalBitmap);
				linearLayoutBottom.addView(screenshotRow);
			} else {
				Log.d(TAG, "using screenshotRow with id "
						+ (1231 + currentBackdropPosition / sScreenshotsInRowPortrait));
				screenshotRow = (LinearLayout) linearLayoutBottom.findViewById(1231 + currentBackdropPosition
						/ sScreenshotsInRowPortrait);
				setBitmapToImageView(currentBackdropBitmap, screenshotRow, currentBackdropPosition,
						sScreenshotsInRowPortrait, finalBitmap);
				linearLayoutBottom.removeView(screenshotRow);
				linearLayoutBottom.addView(screenshotRow);
			}
		} else {
			/* orientation is landscape, so only max 8 imageviews need to be set */
			Log.d(TAG, "ORIENTATION_LANDSCAPE");
			LinearLayout screenshotRow;

			if (currentBackdropPosition % sScreenshotsInRowLandscape == 0) {
				Log.d(TAG, "creating screenshotRow with id "
						+ (2456 + currentBackdropPosition / sScreenshotsInRowLandscape));
				screenshotRow = (LinearLayout) View.inflate(getActivity(), R.layout.screen_shots_row_land, null);
				screenshotRow.setId(2456 + currentBackdropPosition / sScreenshotsInRowLandscape);
				setBitmapToImageView(currentBackdropBitmap, screenshotRow, currentBackdropPosition,
						sScreenshotsInRowLandscape, finalBitmap);
				linearLayoutBottom.addView(screenshotRow);
			} else {
				Log.d(TAG, "using screenshotRow with id "
						+ (2456 + currentBackdropPosition / sScreenshotsInRowLandscape));
				screenshotRow = (LinearLayout) linearLayoutBottom.findViewById(2456 + currentBackdropPosition
						/ sScreenshotsInRowLandscape);
				setBitmapToImageView(currentBackdropBitmap, screenshotRow, currentBackdropPosition,
						sScreenshotsInRowLandscape, finalBitmap);
				linearLayoutBottom.removeView(screenshotRow);
				linearLayoutBottom.addView(screenshotRow);
			}
		}
	}

	private void setBitmapToImageView(final Bitmap currentBackdropBitmap, final LinearLayout screenshotRow,
			final int position, final int orientation, final boolean finalBitmap) {

		Log.d(TAG, "from setBitmapToImageView() position is " + position);
		FrameLayout frame = (FrameLayout) screenshotRow.getChildAt(position % orientation);
		frame.getChildAt(0).setVisibility(View.GONE);
		ImageView currentBackdrop = (ImageView) frame.getChildAt(1);
		if (currentBackdropBitmap != null) {
			currentBackdrop.setImageBitmap(currentBackdropBitmap);
		} else {
			currentBackdrop.setImageResource(R.drawable.not_available);
		}

		currentBackdrop.setOnClickListener(this);
		currentBackdrop.setId(position);

		if (position % orientation != orientation - 1 && !finalBitmap) {
			FrameLayout next = (FrameLayout) screenshotRow.getChildAt((position + 1) % orientation);
			next.getChildAt(0).setVisibility(View.VISIBLE);
		}

	}

	@Override
	public void onClick(final View v) {
		if (v.getId() == R.id.details_play_trailer) {
			Intent i = new Intent(Intent.ACTION_VIEW);
			i.setDataAndType(Uri.parse(movieDetails.getTrailerUrl()), "video/*");
			startActivity(i);
		} else {
			Intent i = new Intent(Intent.ACTION_VIEW);
			int hdUrlPosition = movieDetails.getBackdropHDUrls().size() - 1 - v.getId();
			Log.d(TAG, "clicked on " + v.getId());
			Log.d(TAG, "gonna get " + hdUrlPosition);
			i.setData(Uri.parse(movieDetails.getBackdropHDUrls().get(hdUrlPosition)));
			startActivity(i);
		}
	}
}
